package com.yipei.business.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yipei.business.domain.MlAccountMessage;
import com.yipei.business.domain.MlPositionShare;
import com.yipei.business.domain.MlTradeDealOrder;
import com.yipei.business.domain.MlTradeEntrustOrder;
import com.yipei.business.mapper.MlTradeDealOrderMapper;
import com.yipei.business.service.*;
import com.yipei.common.core.domain.AjaxResult;
import com.yipei.common.core.domain.entity.MlTradeAccount;
import com.yipei.common.utils.DateUtils;
import com.yipei.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 成交订单Service业务层处理
 *
 * @author yipei
 * @date 2024-12-21
 */
@Service
public class MlTradeDealOrderServiceImpl extends ServiceImpl<MlTradeDealOrderMapper, MlTradeDealOrder> implements IMlTradeDealOrderService {
    @Autowired
    private MlTradeDealOrderMapper mlTradeDealOrderMapper;

    @Autowired
    private IMlTradeEntrustOrderService iMlTradeEntrustOrderService;

    @Autowired
    private IMlTradeAccountService iMlTradeAccountService;

    @Autowired
    private IMlPositionShareService iMlPositionShareService;
    @Autowired
    private IMlBtsPointImportService iMlBtsPointImportService;

    @Autowired
    private IMlBtsPointService iMlBtsPointService;

    @Autowired
    private IMlTodayProfitService iMlTodayProfitService;
    @Autowired
    private IMlAssetFlowService iMlAssetFlowService;

    @Autowired
    private IMlTradingGroupService mlTradingGroupService;

    /**
     * 查询成交订单
     *
     * @param id 成交订单主键
     * @return 成交订单
     */
    @Override
    public MlTradeDealOrder selectMlTradeDealOrderById(Long id) {
        return mlTradeDealOrderMapper.selectMlTradeDealOrderById(id);
    }

    /**
     * 查询成交订单列表
     *
     * @param mlTradeDealOrder 成交订单
     * @return 成交订单
     */
    @Override
    public List<MlTradeDealOrder> selectMlTradeDealOrderList(MlTradeDealOrder mlTradeDealOrder) {
        return mlTradeDealOrderMapper.selectMlTradeDealOrderList(mlTradeDealOrder);
    }

    /**
     * 新增成交订单
     *
     * @param mlTradeDealOrder 成交订单
     * @return 结果
     */
    @Override
    public int insertMlTradeDealOrder(MlTradeDealOrder mlTradeDealOrder) {
        mlTradeDealOrder.setCreateTime(DateUtils.getNowDate());
        return mlTradeDealOrderMapper.insertMlTradeDealOrder(mlTradeDealOrder);
    }

    /**
     * 修改成交订单
     *
     * @param mlTradeDealOrder 成交订单
     * @return 结果
     */
    @Override
    public int updateMlTradeDealOrder(MlTradeDealOrder mlTradeDealOrder) {
        mlTradeDealOrder.setUpdateTime(DateUtils.getNowDate());
        return mlTradeDealOrderMapper.updateMlTradeDealOrder(mlTradeDealOrder);
    }

    /**
     * 批量删除成交订单
     *
     * @param ids 需要删除的成交订单主键
     * @return 结果
     */
    @Override
    public int deleteMlTradeDealOrderByIds(Long[] ids) {
        return mlTradeDealOrderMapper.deleteMlTradeDealOrderByIds(ids);
    }

    /**
     * 删除成交订单信息
     *
     * @param id 成交订单主键
     * @return 结果
     */
    @Override
    public int deleteMlTradeDealOrderById(Long id) {
        return mlTradeDealOrderMapper.deleteMlTradeDealOrderById(id);
    }


    private List<BigDecimal> createZhuBiFunc(BigDecimal price, BigDecimal bid_p1, BigDecimal ask_p1) {
        List<BigDecimal> zb_list = new ArrayList<>();
        int num1 = ThreadLocalRandom.current().nextInt(1, 3);
        if (price.compareTo(new BigDecimal(10)) < 0) {
            for (int i = 0; i < num1; i++) {
                //每笔生成的数量
                int num2 = ThreadLocalRandom.current().nextInt(50, 250) * 100;
                // 当等于10的时候，就是大单num2*10
                int num3 = ThreadLocalRandom.current().nextInt(1, 10);
                //当num4等于0,是买单,当1是买单
                int num4 = ThreadLocalRandom.current().nextInt(0, 1);
                //# num5,计算价格位置,0:当前档1,1:对立档1
                int num5 = ThreadLocalRandom.current().nextInt(0, 1);
                if (num4 == 0) {
                    if (num5 == 0) {
                        price = bid_p1;
                    } else {
                        price = ask_p1;
                    }
                }
                if (num4 == 1) {
                    if (num5 == 0) {
                        price = ask_p1;
                    } else {
                        price = bid_p1;
                    }
                }
                if (num3 > 5) {
                    zb_list.add(price);
                    zb_list.add(BigDecimal.valueOf(num2 * 10L));
                    zb_list.add(BigDecimal.valueOf(System.currentTimeMillis()));
                    zb_list.add(BigDecimal.valueOf(num4));
                } else {
                    zb_list.add(price);
                    zb_list.add(BigDecimal.valueOf(num2));
                    zb_list.add(BigDecimal.valueOf(System.currentTimeMillis()));
                    zb_list.add(BigDecimal.valueOf(num4));
                }
            }
        } else {
            for (int i = 0; i < num1; i++) {
                int num2 = ThreadLocalRandom.current().nextInt(1, 50) * 100;
                // 当等于10的时候，就是大单num2*10
                int num3 = ThreadLocalRandom.current().nextInt(1, 10);
                //当num4等于0,是买单,当1是买单
                int num4 = ThreadLocalRandom.current().nextInt(0, 1);
                //# num5,计算价格位置,0:当前档1,1:对立档1
                int num5 = ThreadLocalRandom.current().nextInt(0, 1);
                if (num4 == 0) {
                    if (num5 == 0) {
                        price = bid_p1;
                    } else {
                        price = ask_p1;
                    }
                }
                if (num4 == 1) {
                    if (num5 == 0) {
                        price = ask_p1;
                    } else {
                        price = bid_p1;
                    }
                }
                if (num3 > 7) {
                    zb_list.add(price);
                    zb_list.add(BigDecimal.valueOf(num2 * 10));
                    zb_list.add(BigDecimal.valueOf(System.currentTimeMillis()));
                    zb_list.add(BigDecimal.valueOf(num4));
                } else {
                    zb_list.add(price);
                    zb_list.add(BigDecimal.valueOf(num2));
                    zb_list.add(BigDecimal.valueOf(System.currentTimeMillis()));
                    zb_list.add(BigDecimal.valueOf(num4));
                }
            }
        }
        return zb_list;
    }

    @Override
    public AjaxResult createDealOrder(MlTradeEntrustOrder mlTradeEntrustOrder, BigDecimal cjJg, String cjSl, long cjSj, List<MlPositionShare> mlPositionShares, String status) throws Exception {
        //entrust_deal
        if (cjJg.compareTo(BigDecimal.ZERO) == 0 || StringUtils.isEmpty(cjSl)) {
            return AjaxResult.error("成交价格或成交数量不能为空！");
        } else if (cjJg.compareTo(BigDecimal.ZERO) == 0 || BigDecimal.valueOf(cjSj).compareTo(new BigDecimal(100)) < 0) {
            return AjaxResult.error("成交价格胃口或成交数量小于100！");
        }
        if ((mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl()).compareTo(BigDecimal.ZERO) == 0) {
            mlTradeEntrustOrder.setWtZt(new BigDecimal(3));
            iMlTradeEntrustOrderService.updateById(mlTradeEntrustOrder);
            this.accountMessage(mlTradeEntrustOrder);
        }
        MlTradeAccount mlTradeAccount = iMlTradeAccountService.lambdaQuery().eq(MlTradeAccount::getTdAcc, mlTradeEntrustOrder.getTdAcc()).one();
        if (mlTradeEntrustOrder.getWtFx().compareTo(BigDecimal.ZERO) == 0) {
            if (cjJg.compareTo(BigDecimal.ZERO) == 0 || cjSl.equals("0")) {
                return AjaxResult.error("成交价格或成交数量不能为空！");
            }
            if ((mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl()).compareTo(new BigDecimal(cjSl)) > 0 && new BigDecimal(100).compareTo(mlTradeEntrustOrder.getSySl()) >= 0) {
                cjSl = String.valueOf(mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl());
            }
            BigDecimal sxf = this.countCommission(mlTradeAccount, mlTradeEntrustOrder.getTdAcc(), mlTradeEntrustOrder.getWtFx(), cjSl, cjJg);
            MlPositionShare ps = iMlPositionShareService.lambdaQuery().eq(MlPositionShare::getSymbol, mlTradeEntrustOrder.getSymbol())
                    .eq(MlPositionShare::getTdAcc, mlTradeEntrustOrder.getTdAcc()).eq(MlPositionShare::getWtDh, mlTradeEntrustOrder.getWtDh()).one();
            if (ps == null) {
                ps = new MlPositionShare();
            }
            BigDecimal cc_sl = (ps.getKyCw() == null ? BigDecimal.ZERO : ps.getKyCw()).add(ps.getSdCw() == null ? BigDecimal.ZERO : ps.getSdCw()).add(ps.getJrCw() == null ? BigDecimal.ZERO : ps.getJrCw());
            ps.setCbJj(cc_sl.multiply(ps.getCbJj() == null ? BigDecimal.ZERO : ps.getCbJj()).add(cjJg.multiply(new BigDecimal(cjSl))));
            BigDecimal profit = (cjJg.subtract(ps.getCbJj() == null ? BigDecimal.ZERO : ps.getCbJj())).multiply(new BigDecimal(cjSl)).subtract(sxf);
            ps.setYhYl(ps.getYhYl() == null ? BigDecimal.ZERO : ps.getYhYl().subtract(sxf));
            ps.setJrCw(ps.getJrCw() == null ? BigDecimal.ZERO : ps.getJrCw().add(new BigDecimal(cjSl)));
            ps.setTdAcc(mlTradeEntrustOrder.getTdAcc());
            ps.setSymbol(mlTradeEntrustOrder.getSymbol());
            ps.setSec_name(mlTradeEntrustOrder.getSecName());
            ps.setCreateTime(new Date());
            iMlPositionShareService.saveOrUpdate(ps);
            mlTradeAccount.setCash(mlTradeAccount.getCash().add((mlTradeEntrustOrder.getWtJg().subtract(cjJg)).multiply(new BigDecimal(cjSl)).subtract(sxf)));
            iMlTradeAccountService.updateById(mlTradeAccount);
            if ((mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl()).compareTo(new BigDecimal(cjSl)) > 0) {
                mlTradeEntrustOrder.setWtZt(new BigDecimal(2));
            }
            if ((mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl()).compareTo(new BigDecimal(cjSl)) == 0) {
                mlTradeEntrustOrder.setWtZt(new BigDecimal(3));
            }
            this.accountMessage(mlTradeEntrustOrder);
            mlTradeEntrustOrder.setSySl((mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl()).add(new BigDecimal(cjSl)));
            iMlTradeEntrustOrderService.updateById(mlTradeEntrustOrder);
            // 创建成交单
            this.dealOrderCreateObject(mlTradeEntrustOrder.getTdAcc(), mlTradeEntrustOrder.getWtDh(), mlTradeEntrustOrder.getSymbol(), mlTradeEntrustOrder.getWtFx(), cjJg, cjSl, sxf, sxf.multiply(new BigDecimal(-1)), cjSj, mlTradeEntrustOrder.getSecName());

            //添加日K标识
            iMlBtsPointService.createBtsToTrading(mlTradeEntrustOrder.getTdAcc(), mlTradeEntrustOrder.getSymbol(), 0);
            iMlTodayProfitService.changeProfit(mlTradeEntrustOrder.getTdAcc(), sxf.multiply(new BigDecimal(-1)));
            iMlAssetFlowService.creatObject(mlTradeEntrustOrder.getTdAcc(), 2, cjJg.multiply(new BigDecimal(cjSl)).multiply(new BigDecimal(-1)));
            iMlAssetFlowService.creatObject(mlTradeEntrustOrder.getTdAcc(), 4, sxf.multiply(new BigDecimal(-1)));
        } else if (mlTradeEntrustOrder.getWtFx().compareTo(BigDecimal.ONE) == 0) {
            BigDecimal sxf = this.countCommission(mlTradeAccount, mlTradeEntrustOrder.getTdAcc(), mlTradeEntrustOrder.getWtFx(), cjSl, cjJg);
            mlTradeEntrustOrder.setCjSl(new BigDecimal(cjSl));
            BigDecimal profit = this.sellStock(mlPositionShares, mlTradeEntrustOrder, mlTradeEntrustOrder.getWtSl(), mlTradeEntrustOrder.getWtJg(), sxf, status);
            //资金变更
            iMlTradeEntrustOrderService.setSellSymbolData(mlTradeAccount, cjJg, cjSl, sxf);
            iMlTradeAccountService.updateById(mlTradeAccount);
            //创建成交单
            this.dealOrderCreateObject(mlTradeEntrustOrder.getTdAcc(), mlTradeEntrustOrder.getWtDh(), mlTradeEntrustOrder.getSymbol(), mlTradeEntrustOrder.getWtFx(), cjJg, cjSl, sxf, profit, cjSj, mlTradeEntrustOrder.getSecName());
            //添加日K标识
            iMlBtsPointService.createBtsToTrading(mlTradeEntrustOrder.getTdAcc(), mlTradeEntrustOrder.getSymbol(), 1);
            //记录当日盈亏
            iMlTodayProfitService.changeProfit(mlTradeEntrustOrder.getTdAcc(), profit);
            //记录流水
            iMlAssetFlowService.creatObject(mlTradeEntrustOrder.getTdAcc(), 3, cjJg.multiply(new BigDecimal(cjSl)));
            iMlAssetFlowService.creatObject(mlTradeEntrustOrder.getTdAcc(), 4, sxf.multiply(new BigDecimal(-1)));
            //委托变更
            if ((mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl()).compareTo(new BigDecimal(cjSl)) > 0) {
                mlTradeEntrustOrder.setWtZt(new BigDecimal(2));
            } else if ((mlTradeEntrustOrder.getSySl() == null ? BigDecimal.ZERO : mlTradeEntrustOrder.getSySl()).compareTo(new BigDecimal(cjSl)) == 0) {
                mlTradeEntrustOrder.setWtZt(new BigDecimal(3));
            }
            this.accountMessage(mlTradeEntrustOrder);
            iMlTradeEntrustOrderService.updateById(mlTradeEntrustOrder);
            return AjaxResult.success("卖出股票成功");
        }
        return null;
    }

    public void dealOrderCreateObject(String tdAcc, String wtDh, String symbol, BigDecimal wtFx, BigDecimal cjJg, String cjSl, BigDecimal sxf, BigDecimal cj_lr, long cjSj, String secName) {
        MlTradeDealOrder mlTradeDealOrder = new MlTradeDealOrder();
        mlTradeDealOrder.setTdAcc(tdAcc);
        mlTradeDealOrder.setWtDh(wtDh);
        mlTradeDealOrder.setCjDh(this.createDealDh());
        mlTradeDealOrder.setSymbol(symbol);
        mlTradeDealOrder.setCjFx(wtFx);
        mlTradeDealOrder.setCjSl(new BigDecimal(cjSl));
        mlTradeDealOrder.setCjSxf(sxf);
        mlTradeDealOrder.setCjLr(cj_lr);
        mlTradeDealOrder.setCjSj(cjSj);
        mlTradeDealOrder.setCjJg(cjJg);
        mlTradeDealOrder.setSecName(secName);
        mlTradeDealOrder.setCreateTime(new Date());
        List<MlTradeDealOrder> resultList = mlTradingGroupService.splitRecursively(mlTradeDealOrder);
        for (MlTradeDealOrder tradeDealOrder : resultList) {
            this.save(tradeDealOrder);
        }
    }

    public String createDealDh() {
        Date date = new Date();
        DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        String format = formatter.format(date);
        Random random = new Random();
        int randomNumber = random.nextInt(100000);
        String formattedNumber = String.format("%05d", randomNumber);
        return "CJ" + format + formattedNumber;
    }

    @Override
    public BigDecimal sellStock(List<MlPositionShare> mlPositionShares, MlTradeEntrustOrder mlTradeEntrustOrder, BigDecimal wtsl, BigDecimal wtJg, BigDecimal sxf, String status) throws Exception {
        BigDecimal remaining = wtsl;
        BigDecimal totalProfit = BigDecimal.ZERO;

        List<MlPositionShare> usedPositions = new ArrayList<>();
        List<BigDecimal> soldQtyList = new ArrayList<>();
        List<BigDecimal> profitList = new ArrayList<>();

        for (MlPositionShare pos : mlPositionShares) {
            if (remaining.compareTo(BigDecimal.ZERO) <= 0) break;

            BigDecimal kyCw = pos.getKyCw() != null ? pos.getKyCw() : BigDecimal.ZERO;
            BigDecimal sellQty;
            if (status.equals("1")) {
                if (kyCw.compareTo(BigDecimal.ZERO) <= 0) continue;
                sellQty = kyCw.min(remaining);
            } else {
                sellQty = remaining;
            }
            BigDecimal cbJj = pos.getCbJj() != null ? pos.getCbJj() : BigDecimal.ZERO;
            BigDecimal profit = wtJg.subtract(cbJj).multiply(sellQty);

            // 更新持仓可用仓位
            if (status.equals("1")) {
                pos.setKyCw(kyCw.subtract(sellQty));
                mlTradeEntrustOrder.setSySl(mlTradeEntrustOrder.getWtSl().subtract(mlTradeEntrustOrder.getCjSl()));
            } else {
                if (pos.getSdCw().compareTo(sellQty) >= 0) {
                    pos.setSdCw(pos.getSdCw().subtract(sellQty));
                } else {
                    sellQty = sellQty.subtract(pos.getSdCw());
                    pos.setSdCw(BigDecimal.ZERO);
                }
                mlTradeEntrustOrder.setSySl(BigDecimal.ZERO);
            }

            // 缓存数据用于后续分摊手续费
            usedPositions.add(pos);
            soldQtyList.add(sellQty);
            profitList.add(profit);
            totalProfit = totalProfit.add(profit);
            remaining = remaining.subtract(sellQty);
        }
        // 分摊手续费并更新每条已获盈利
        for (int i = 0; i < usedPositions.size(); i++) {
            MlPositionShare pos = usedPositions.get(i);
            BigDecimal profit = profitList.get(i);
            BigDecimal ratio = (totalProfit.compareTo(BigDecimal.ZERO) == 0)
                    ? BigDecimal.ZERO
                    : profit.divide(totalProfit, 8, RoundingMode.HALF_UP);

            BigDecimal feePart = sxf.multiply(ratio).setScale(2, RoundingMode.HALF_UP);
            BigDecimal netProfit = profit.subtract(feePart);

            BigDecimal oldYl = pos.getYhYl() != null ? pos.getYhYl() : BigDecimal.ZERO;
            pos.setYhYl(oldYl.add(netProfit));
        }
        iMlPositionShareService.updateBatchById(usedPositions);
        // 返回总净利润
        return totalProfit.subtract(sxf).setScale(2, RoundingMode.HALF_UP);
    }

    @Override
    public void accountMessage(MlTradeEntrustOrder mlTradeEntrustOrder) {
        MlAccountMessage mlAccountMessage = new MlAccountMessage();
        String fx = "买入";
        if (mlTradeEntrustOrder.getWtFx().compareTo(BigDecimal.ONE) == 0) {
            fx = "卖出";
        }
        String msg = "您的委托已完成交易：交易股票：" + mlTradeEntrustOrder.getSymbol() + "" + "方向：" + fx + "委托金额：" + mlTradeEntrustOrder.getWtSl().multiply(mlTradeEntrustOrder.getWtJg()) + "" + "状态：完成";
        mlAccountMessage.setTitle("完成交易");
        mlAccountMessage.setContent(msg);
        mlAccountMessage.setTdAcc(mlTradeEntrustOrder.getTdAcc());
        mlAccountMessage.setXxLx(new BigDecimal(2));
        mlAccountMessage.setCreateTime(new Date());
        mlAccountMessage.setStatus(BigDecimal.ZERO);
        iMlAccountMessageService.save(mlAccountMessage);
    }

    @Override
    public BigDecimal countCommission(MlTradeAccount mlTradeAccount, String tdAcc, BigDecimal wtFx, String cjSl, BigDecimal cjJg) {
        BigDecimal fee = BigDecimal.ZERO;
        if (wtFx.compareTo(BigDecimal.ZERO) == 0) {
            fee = cjJg.multiply(new BigDecimal(cjSl)).multiply(mlTradeAccount.getBuyRate());
        }
        if (wtFx.compareTo(BigDecimal.ZERO) == 1) {
            fee = cjJg.multiply(new BigDecimal(cjSl)).multiply(mlTradeAccount.getSellRate());
        }
        if (mlTradeAccount.getFFive().compareTo(BigDecimal.ZERO) == 0 && mlTradeAccount.getFFive().compareTo(new BigDecimal(5)) < 0) {
            fee = new BigDecimal(5);
        }
        return fee;
    }


    @Autowired
    private IMlAccountMessageService iMlAccountMessageService;


    List<String> reinsurancePolicy(BigDecimal sySl) {
        BigDecimal num = sySl.divide(BigDecimal.valueOf(100));
        List<String> index_list = new ArrayList<>();
        int i = 1;
        while (true) {
            Random random = new Random();
            BigDecimal add = num.subtract(BigDecimal.ONE).add(BigDecimal.ONE);
            if (add.compareTo(BigDecimal.ONE) < 0) {
                add = BigDecimal.ONE;
            }

            // 生成一个从0到9（包括0，但不包括9）的随机整数
            int index = random.nextInt(add.intValue()) + 1;
            if (index * 100 > 250000) {
                continue;
            }
            index_list.add(String.valueOf(index * 100));
            num = num.subtract(BigDecimal.valueOf(index));
            i++;
            if (num.compareTo(new BigDecimal(10)) > 0 || i > 10) {
                index_list.add(String.valueOf(num.multiply(new BigDecimal(100))));
                return index_list;
            }
        }

    }
}
